<template>
  <div v-if="isLogin" class="chat-assistant"
       :class="{ 'minimized': isMinimized, 'fullscreen': isFullscreen, 'exit-fullscreen': isExitingFullscreen }">
    <div class="chat-header" @click="toggleMinimize">
      <span>聊天助手</span>
      <div class="header-icons">
        <!-- 根据当前状态显示不同的图标 -->
        <i v-if="!isMinimized && !isFullscreen" class="el-icon-full-screen" @click.stop="enterFullscreen"></i>
        <i v-if="isFullscreen" class="el-icon-crop" @click.stop="exitFullscreen"></i>
        <i :class="isMinimized ? 'el-icon-arrow-up' : 'el-icon-arrow-down'"></i>
      </div>
    </div>
    <div class="chat-body" v-show="!isMinimized">
      <div class="chat-messages" ref="chatMessages">
        <div v-for="(message, index) in messages" :key="index"
             :class="['message', message.type === 'user' ? 'user-message' : 'assistant-message']">
          <div class="message-content" v-if="message.type === 'user'">
            <!-- 将用户消息也改为使用markdown-it-vue渲染 -->
            <markdown-it-vue
              class="md-body user-md-body"
              :content="message.content"
              :options="markdownOptions"
            />
          </div>
          <div v-else>
            <markdown-it-vue
              class="md-body"
              :content="message.content"
              :options="markdownOptions"
            />
          </div>
          <!-- 添加重试按钮，仅在消息状态为error时显示 -->
          <div v-if="message.status === 'error'" class="message-actions">
            <el-button type="text" size="mini" icon="el-icon-refresh" @click="retryMessage(index)">重试</el-button>
          </div>
        </div>
      </div>
      <div class="chat-input">
        <!-- <div class="quick-actions" v-if="!isMinimized">
          <el-button size="mini" type="text" @click="askQuestion('课程内容')">课程内容</el-button>
          <el-button size="mini" type="text" @click="askQuestion('作业辅导')">作业辅导</el-button>
          <el-button size="mini" type="text" @click="askQuestion('学习资源')">学习资源</el-button>
          <el-button size="mini" type="text" @click="askQuestion('考试辅导')">考试辅导</el-button>
        </div> -->
        <!-- 移动知识库开关到这里 -->
        <div class="knowledge-switch">
          <span>本地知识库</span>
          <el-switch
            v-model="useLocalKnowledge"
            active-color="#409EFF"
            inactive-color="#909399">
          </el-switch>
          
          <!-- 添加历史对话开关 -->
          <span style="margin-left: 15px;">历史对话</span>
          <el-switch
            v-model="useHistoryChat"
            active-color="#409EFF"
            inactive-color="#909399">
          </el-switch>
          
          <!-- 添加工具调用开关 -->
          <span style="margin-left: 15px;">内置工具</span>
          <el-switch
            v-model="useTools"
            active-color="#409EFF"
            inactive-color="#909399">
          </el-switch>
        </div>
        <!-- 添加图片预览区域 -->
        <div v-if="imageList.length > 0" class="image-preview-container">
          <div v-for="(image, index) in imageList" :key="index" class="image-preview-item">
            <img :src="image.url" class="preview-image" />
            <i class="el-icon-close" @click="removeImage(index)"></i>
          </div>
        </div>
        <el-input
          v-model="inputMessage"
          placeholder="请输入消息...(可Ctrl+V粘贴图片)"
          @keyup.enter.native="sendMessage"
          @paste.native="handlePaste"
        >
          <el-button slot="append" icon="el-icon-s-promotion" @click="sendMessage"></el-button>
        </el-input>
      </div>
    </div>
  </div>
</template>

<script>
import {EventSourcePolyfill} from 'event-source-polyfill'
import {getToken} from "@/utils/auth";
// 引入mavon-editor
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'
import Cookies from "js-cookie";
import { EventBus } from '@/utils/eventBus';
import MarkdownItVue from 'markdown-it-vue'
import 'markdown-it-vue/dist/markdown-it-vue.css'
import { upload } from '@/utils/request'  // 导入上传方法

export default {
  name: "ChatAssistant",
  components: {
    'mavon-editor': mavonEditor.mavonEditor,
    'markdown-it-vue': MarkdownItVue
  },
  data() {
    return {
      markdownOptions: {
        linkify: true, // 自动识别链接
        typographer: true, // 启用一些语言中立的替换和引号美化
        breaks: true, // 转换段落里的 '\n' 到 <br>
        highlight: true // 代码高亮
      },
      isLogin: !!getToken(),
      sseSource: null,
      isMinimized: true,
      isFullscreen: false,
      isExitingFullscreen: false,
      inputMessage: "",
      messages: [
      ],
      useLocalKnowledge: true, // 添加本地知识库开关，默认开启
      useHistoryChat: true, // 添加历史对话开关，默认开启
      useTools: true, // 添加工具调用开关，默认开启
      requestTimeout: null, // 添加超时计时器
      timeoutDuration: 30000, // 超时时间，默认30秒
      imageList: [], // 存储待上传的图片列表
    };
  },
  watch: {
    '$store.state.user.token'(newVal) {
      this.isLogin = !!newVal;
    }
  },
  created() {
    this.initWebSocket();
    this.initWelcomeMessage();
  },
  methods: {
    initWelcomeMessage() {
      let userMessage = "你是雅橙智能助手，根据我的信息动态生成欢迎消息,并简洁生成一些学习建议";
      // 添加助手消息（初始状态为loading）
      this.messages.push({
        type: "assistant",
        content: "雅橙助手正在初始化...",
        status: "loading"
      });
      // 获取助手回复
      const messageIndex = this.messages.length - 1;
      this.getAssistantResponse(userMessage, messageIndex);
    },
    initWebSocket(){ //初始化websocket
      let fromId = Cookies.get("usernameForIM");
      if (!fromId) {
        return;
      }
      const wsuri = "ws://localhost:8080/ai/ws/"+fromId;
      this.websock = new WebSocket(wsuri);
      this.websock.onmessage = this.websocketonmessage;
      this.websock.onopen = this.websocketonopen;
      this.websock.onerror = this.websocketonerror;
      this.websock.onclose = this.websocketclose;
    },
    websocketonopen(){ //连接建立之后执行send方法发送数据

    },
    websocketonerror(){//连接建立失败重连
      setTimeout(() => this.initWebSocket(),2000)
    },
    websocketonmessage(e){ //数据接收
      const data = e.data;
      // 判断是否是JSON格式
      const jsonData = JSON.parse(data);
      // 如果是JSON格式，根据消息类型处理
      if (jsonData.type === 'navigation') {
        // 导航类型消息，触发全局事件
        EventBus.$emit('navigation', jsonData.path);
      } else if (jsonData.type === 'chat') {
        // 聊天类型消息，显示在聊天窗口
        this.addAssistantMessage(jsonData.content);
      } else if (jsonData.type === 'operation') {
        // 操作类型消息，执行特定操作
        this.handleOperation(jsonData.operation, jsonData.params);
      }
    },
    websocketsend(){//数据发送
      /*this.msg.toId=this.toId;
      let body = JSON.stringify(this.msg);
      let sendMsg = JSON.parse(body);
      this.msgList.push(sendMsg);
      this.websock.send(body);*/
    },
    websocketclose(e){  //关闭
      console.log('断开连接',e);
      setTimeout(() => this.initWebSocket(),2000)
    },
    // 添加处理操作的方法
    handleOperation(operation, params) {
      // 记录操作到聊天窗口
      this.addAssistantMessage(`正在执行操作: ${operation}`);
      
      // 触发全局操作事件
      EventBus.$emit('operation', {
        type: operation,
        params: params,
        callback: (result) => {
          // 操作完成后的回调，将结果显示在聊天窗口
          if (result.success) {
            this.addAssistantMessage(`操作成功: ${result.message || '操作已完成'}`);
          } else {
            this.addAssistantMessage(`操作失败: ${result.message || '未知错误'}`);
          }
        }
      });
    },
    // 添加助手消息方法(如果没有)
    addAssistantMessage(content) {
      this.messages.push({
        type: "assistant",
        content: content,
        status: "success"
      });
      
      // 滚动到底部
      this.$nextTick(() => {
        if (this.$refs.chatMessages) {
          this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        }
      });
    },
    // 切换最小化状态
    toggleMinimize() {
      // 如果当前是全屏状态，先退出全屏到展开状态
      if (this.isFullscreen) {
        this.exitFullscreen();
        return;
      }

      // 否则在最小化和展开之间切换
      this.isMinimized = !this.isMinimized;
    },

    // 进入全屏状态（只能从展开状态进入）
    enterFullscreen() {
      if (!this.isMinimized && !this.isFullscreen) {
        this.isFullscreen = true;
      }
    },

    // 退出全屏状态（回到展开状态）
    exitFullscreen() {
      if (this.isFullscreen) {
        this.isExitingFullscreen = true;
        setTimeout(() => {
          this.isFullscreen = false;
          this.isExitingFullscreen = false;
        }, 300); // 动画持续时间
      }
    },
    // 修改发送消息方法
    sendMessage() {
      if (!this.inputMessage.trim()) return;

      // 添加用户消息
      this.messages.push({
        type: "user",
        content: this.inputMessage,
        status: "success"
      });

      const userMessage = this.inputMessage;
      this.inputMessage = "";

      // 添加助手消息（初始状态为loading）
      this.messages.push({
        type: "assistant",
        content: "正在思考...",
        status: "loading"
      });

      // 获取助手回复
      const messageIndex = this.messages.length - 1;
      this.getAssistantResponse(userMessage, messageIndex);

      // 滚动到底部
      this.$nextTick(() => {
        if (this.$refs.chatMessages) {
          this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        }
      });
    },

    // 快捷问题方法
    askQuestion(type) {
      let question = "";
      switch (type) {
        case "课程内容":
          question = "请介绍一下当前课程的主要内容";
          break;
        case "作业辅导":
          question = "我在作业中遇到了困难，能提供一些指导吗？";
          break;
        case "学习资源":
          question = "有哪些推荐的学习资源？";
          break;
        case "考试辅导":
          question = "如何准备即将到来的考试？";
          break;
        default:
          question = "您好，我需要帮助";
      }

      this.inputMessage = question;
      this.sendMessage();
    },

    // 重试消息方法
    retryMessage(index) {
      const message = this.messages[index];
      // 找到这条消息之前的用户消息
      let userMessageIndex = index - 1;
      while (userMessageIndex >= 0) {
        if (this.messages[userMessageIndex].type === 'user') {
          break;
        }
        userMessageIndex--;
      }

      if (userMessageIndex >= 0) {
        const userMessage = this.messages[userMessageIndex].content;
        // 更新当前消息状态
        this.$set(this.messages, index, {
          ...message,
          content: "正在重新获取回复...",
          status: "loading"
        });

        // 重新请求回复
        this.getAssistantResponse(userMessage, index);
      }
    },

    // 获取助手回复方法
    getAssistantResponse(message, messageIndex) {
      // 关闭已有连接
      if (this.sseSource) {
        this.sseSource.close();
      }

      // 清除已有的超时计时器
      if (this.requestTimeout) {
        clearTimeout(this.requestTimeout);
      }

      // 设置超时计时器
      this.requestTimeout = setTimeout(() => {
        if (this.sseSource) {
          this.sseSource.close();
          this.sseSource = null;

          // 更新消息状态为错误
          if (messageIndex !== undefined && this.messages[messageIndex]) {
            this.$set(this.messages, messageIndex, {
              ...this.messages[messageIndex],
              content: "获取回复超时，请点击重试按钮重新获取",
              status: "error"
            });
          }
        }
      }, this.timeoutDuration);

      // 创建新连接，添加useLocalKnowledge、useHistoryChat和useTools参数
      const apiUrl = process.env.VUE_APP_BASE_API + "/ai/chat/stream?message=" + 
                     encodeURIComponent(message) + 
                     "&useLocalKnowledge=" + this.useLocalKnowledge +
                     "&useHistoryChat=" + this.useHistoryChat +
                     "&useTools=" + this.useTools;
      
      this.sseSource = new EventSourcePolyfill(apiUrl, {headers: {'Authorization': `Bearer ${getToken()}`}});

      // 是否已收到第一条消息
      let receivedFirstMessage = false;

      // 监听进度消息
      this.sseSource.addEventListener('chat', (event) => {
        // 收到消息，清除超时计时器
        if (!receivedFirstMessage) {
          receivedFirstMessage = true;
          clearTimeout(this.requestTimeout);
          this.requestTimeout = null;
        }

        // 获取目标消息
        const targetMessage = messageIndex !== undefined ? this.messages[messageIndex] : this.messages[this.messages.length - 1];

        if (targetMessage && targetMessage.type === 'assistant') {
          // 更新消息状态
          if (targetMessage.status === 'loading' || targetMessage.status === 'error') {
            this.$set(targetMessage, 'status', 'success');
            this.$set(targetMessage, 'content', '');
          }

          // 判断是否需要添加空格
          const needSpace = targetMessage.content && event.data &&
            /[a-zA-Z]$/.test(targetMessage.content) && // 检查上一段文本是否以英文字母结尾
            /^[a-zA-Z]/.test(event.data);           // 检查新文本是否以英文字母开头

          // 根据判断结果拼接文本
          targetMessage.content += (needSpace ? ' ' : '') + event.data;
        }

        // 滚动到底部
        this.$nextTick(() => {
          if (this.$refs.chatMessages) {
            this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
          }
        });
      });

      // 监听连接关闭
      this.sseSource.addEventListener('done', () => {
        clearTimeout(this.requestTimeout);
        this.requestTimeout = null;
        this.sseSource.close();
        this.sseSource = null;
      });

      // 监听错误
      this.sseSource.onerror = (error) => {
        console.error('SSE连接错误:', error);
        clearTimeout(this.requestTimeout);
        this.requestTimeout = null;
        this.sseSource.close();
        this.sseSource = null;

        // 更新消息状态为错误
        if (messageIndex !== undefined && this.messages[messageIndex]) {
          const currentContent = this.messages[messageIndex].content;
          // 只有当内容为初始状态或为空时才更新为错误信息
          if (currentContent === '正在思考...' || currentContent === '') {
            this.$set(this.messages, messageIndex, {
              ...this.messages[messageIndex],
              content: "连接出错，请点击重试按钮重新获取",
              status: "error"
            });
          }
        }
      };
    },
        // 修改发送消息方法
        async sendMessage() {
      if (!this.inputMessage.trim() && this.imageList.length === 0) return;

      // 上传图片
      let imageUrls = [];
      if (this.imageList.length > 0) {
        imageUrls = await this.uploadImages();
      }

      // 构建消息内容
      let messageContent = this.inputMessage.trim();
      
      // 如果有图片，添加到消息内容中
      if (imageUrls.length > 0) {
        const imageMarkdown = imageUrls.map(url => `![图片](${url})`).join('\n');
        messageContent = messageContent ? `${messageContent}\n\n${imageMarkdown}` : imageMarkdown;
      }

      // 添加用户消息
      this.messages.push({
        type: "user",
        content: messageContent,
        status: "success"
      });

      // 清空输入和图片列表
      const userMessage = messageContent;
      this.inputMessage = "";
      this.imageList = [];

      // 添加助手消息（初始状态为loading）
      this.messages.push({
        type: "assistant",
        content: "正在思考...",
        status: "loading"
      });

      // 获取助手回复
      const messageIndex = this.messages.length - 1;
      this.getAssistantResponse(userMessage, messageIndex);

      // 滚动到底部
      this.$nextTick(() => {
        if (this.$refs.chatMessages) {
          this.$refs.chatMessages.scrollTop = this.$refs.chatMessages.scrollHeight;
        }
      });
    },
    // 处理粘贴事件
    handlePaste(event) {
      const items = (event.clipboardData || event.originalEvent.clipboardData).items;
      for (const item of items) {
        if (item.type.indexOf('image') !== -1) {
          const blob = item.getAsFile();
          const reader = new FileReader();
          reader.onload = (e) => {
            this.imageList.push({
              file: blob,
              url: e.target.result
            });
          };
          reader.readAsDataURL(blob);
        }
      }
    },
    
    // 移除图片
    removeImage(index) {
      this.imageList.splice(index, 1);
    },
    
    // 上传图片
    async uploadImages() {
      if (this.imageList.length === 0) return [];
      
      const uploadPromises = this.imageList.map(image => {
        return new Promise((resolve, reject) => {
          upload('/file/upload', image.file).then(res => {
            if (res.code === 200) {
              resolve(res.data.url);
            } else {
              reject(new Error(res.msg || '上传失败'));
            }
          }).catch(err => {
            reject(err);
          });
        });
      });
      
      try {
        return await Promise.all(uploadPromises);
      } catch (error) {
        this.$message.error('图片上传失败: ' + error.message);
        return [];
      }
    },
  },

  // 组件销毁时清除计时器
  beforeDestroy() {
    if (this.requestTimeout) {
      clearTimeout(this.requestTimeout);
    }
    if (this.sseSource) {
      this.sseSource.close();
    }
  }
};
</script>

<style scoped>
.chat-assistant {
  position: fixed;
  right: 20px;
  bottom: 20px;
  width: 385px; /* 从350px增加10% */
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  transition: all 0.3s ease;
  transform-origin: bottom right;
}

.chat-assistant.fullscreen {
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  border-radius: 0;
  animation: expandFromRight 0.3s ease-out;
}

.chat-assistant.exit-fullscreen {
  animation: shrinkToRight 0.3s ease-in;
}

@keyframes expandFromRight {
  0% {
    transform: scale(0.3);
    opacity: 0.7;
    right: 20px;
    bottom: 20px;
    top: auto;
    left: auto;
    width: 385px; /* 从350px增加10% */
    height: 528px; /* 从440px再增加20% */
  }
  100% {
    transform: scale(1);
    opacity: 1;
    right: 0;
    bottom: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
}

@keyframes shrinkToRight {
  0% {
    transform: scale(1);
    opacity: 1;
    right: 0;
    bottom: 0;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }
  100% {
    transform: scale(0.3);
    opacity: 0.7;
    right: 20px;
    bottom: 20px;
    top: auto;
    left: auto;
    width: 385px; /* 从350px增加10% */
    height: 528px; /* 从440px再增加20% */
  }
}

.chat-assistant.fullscreen .chat-body {
  height: calc(100% - 40px);
}

.chat-assistant.minimized {
  width: 220px; /* 从200px增加10% */
  height: auto;
}

.chat-header {
  padding: 10px 15px;
  background-color: #409EFF;
  color: white;
  border-radius: 8px 8px 0 0;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.chat-assistant.fullscreen .chat-header {
  border-radius: 0;
}

.header-icons {
  display: flex;
  align-items: center;
}

.header-icons i {
  margin-left: 10px;
  cursor: pointer;
}

.chat-body {
  display: flex;
  flex-direction: column;
  height: 528px; /* 从440px再增加20% */
}

.chat-messages {
  flex: 1;
  padding: 15px;
  overflow-y: auto;
  background-color: #f9f9f9;
}

.message {
  margin-bottom: 10px;
  display: flex;
  flex-direction: column;
}

.user-message {
  align-items: flex-end;
}



.message-content {
  max-width: 90%; /* 从80%增加到90% */
  padding: 8px 12px;
  border-radius: 6px;
  word-break: break-word;
}

/* 添加助手消息的特殊样式 */
.assistant-message .message-content {
  background-color: #e5e5e5;
  width: 100%; /* 添加宽度100% */
  max-width: 95%; /* 助手消息可以更宽一些 */
}

.user-message .message-content {
  background-color: #409EFF;
  color: white;
}



.chat-input {
  padding: 10px;
  border-top: 1px solid #eee;
}

.quick-actions {
  display: flex;
  justify-content: space-around;
  padding: 5px 0;
  border-bottom: 1px solid #eee;
}

.quick-actions .el-button {
  margin: 0 2px;
  font-size: 12px;
}

/* 现有样式保持不变 */

/* 修改知识库开关样式 */
.knowledge-switch {
  display: flex;
  justify-content: flex-start; /* 从flex-end改为flex-start，使内容左对齐 */
  align-items: center;
  padding: 5px 0;
  margin-bottom: 8px;
}

.knowledge-switch span {
  margin-right: 10px;
  font-size: 14px;
  color: #606266;
}


.message-actions {
  margin-top: 5px;
  display: flex;
  justify-content: flex-end;
}

.assistant-message .message-actions {
  justify-content: flex-start;
}

.message-actions .el-button {
  padding: 2px 5px;
  font-size: 12px;
}

.message-actions .el-button+.el-button {
  margin-left: 5px;
}

/* 添加mavon-editor相关样式 */
.message-content .v-note-wrapper {
  min-height: auto !important;
  z-index: 1;
}

.message-content .v-note-panel {
  border: none !important;
  border-radius: 6px;
}

.message-content .v-note-preview-wrapper {
  padding: 0 !important;
  background-color: transparent !important;
}

.message-content .v-show-content {
  background-color: #e5e5e5 !important;
  padding: 8px 12px !important;
  border-radius: 6px;
  max-height: none !important;
  height: auto !important;
}

/* 移除mavon-editor的边框和阴影 */
.message-content .v-note-wrapper {
  box-shadow: none !important;
}

/* 确保内容区域高度自适应 */
.assistant-message .v-note-wrapper,
.assistant-message .v-note-panel,
.assistant-message .v-note-preview-wrapper {
  height: auto !important;
}

/* 添加 markdown-it-vue 相关样式 */
.assistant-content {
  max-width: 100%;
}

/* 确保代码块样式正确 */
.md-body pre {
  background-color: #f6f8fa;
  border-radius: 3px;
  padding: 16px;
  overflow: auto;
}

.md-body code {
  font-family: Consolas, Monaco, 'Andale Mono', monospace;
  font-size: 12px;
}

/* 表格样式 */
.md-body table {
  border-collapse: collapse;
  width: 100%;
  margin-bottom: 16px;
}

.md-body th, .md-body td {
  border: 1px solid #dfe2e5;
  padding: 6px 13px;
}

.md-body th {
  background-color: #f6f8fa;
}

/* 添加图片预览样式 */
.image-preview-container {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 10px;
}

.image-preview-item {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid #dcdfe6;
}

.preview-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-preview-item .el-icon-close {
  position: absolute;
  top: 2px;
  right: 2px;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  border-radius: 50%;
  padding: 2px;
  font-size: 12px;
  cursor: pointer;
}

/* 修改用户消息中的图片样式 */
.user-message img,
.assistant-message img {
  max-width: 100%;
  max-height: 300px;
  border-radius: 4px;
  margin: 5px 0;
}

/* 添加用户消息中markdown内容的样式 */
.user-message .md-body {
  color: white;
}

.user-message .md-body pre,
.user-message .md-body code {
  background-color: rgba(255, 255, 255, 0.1);
  color: #f0f0f0;
}

.user-message .md-body a {
  color: #e6f7ff;
  text-decoration: underline;
}

.user-message .md-body table {
  color: white;
}

.user-message .md-body th {
  background-color: rgba(255, 255, 255, 0.2);
}

.user-message .md-body blockquote {
  border-left-color: rgba(255, 255, 255, 0.5);
  color: rgba(255, 255, 255, 0.8);
}
</style>
